package cn.com.chengmandian.bike.controller;


import cn.com.chengmandian.agent.utils.AuthUtil;
import cn.com.chengmandian.bike.dto.CloseBikeCheckForm;
import cn.com.chengmandian.bike.dto.MemberLocationForm;
import cn.com.chengmandian.bike.model.EbDeviceBike;
import cn.com.chengmandian.bike.model.EbRideOrder;
import cn.com.chengmandian.bike.model.vo.OrderCloseCheckVo;
import cn.com.chengmandian.bike.model.vo.RouteVo;
import cn.com.chengmandian.bike.model.vo.DeviceBikeVo;
import cn.com.chengmandian.bike.service.IEbDeviceBikeService;
import cn.com.chengmandian.bike.service.IEbMemberInfoService;
import cn.com.chengmandian.bike.service.IEbRideOrderService;
import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.core.common.utils.LnglatUtil;
import cn.com.chengmandian.core.redis.cache.AgentParamCacheService;
import cn.com.chengmandian.core.web.pojo.AgentInfo;
import cn.com.chengmandian.core.web.pojo.AgentUser;
import cn.com.chengmandian.core.web.pojo.AjaxResult;
import cn.com.chengmandian.core.web.pojo.BikeAreaParam;
import cn.com.chengmandian.core.web.pojo.BikeParam;
import cn.com.chengmandian.core.web.pojo.amap.Path;
import cn.com.chengmandian.core.web.pojo.amap.Route;
import cn.com.chengmandian.core.web.pojo.amap.Step;
import cn.com.chengmandian.core.web.service.AmapService;
import cn.com.chengmandian.core.web.service.TxMapService;
import cn.com.chengmandian.core.web.utils.LocalMapUtil;
import cn.com.chengmandian.service.bike.IotBikeClient;
import cn.com.chengmandian.service.bike.constants.DeviceCommandEnum;
import cn.com.chengmandian.service.bike.constants.UserTypeEnum;
import cn.com.chengmandian.service.bike.form.SendBikeCommandForm;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * <p>
 * 电单车运营-车辆信息表 前端控制器
 * </p>
 *
 * @author AutoGenerator
 * @since 2021-12-08
 */
@Api(tags = "车辆设备相关接口")
@RestController
@RequestMapping("/device/bike")
public class EbDeviceBikeController {

    @Autowired
    private IEbDeviceBikeService deviceBikeService;

    @Autowired
    private TxMapService txMapService;

    @Autowired
    private AmapService amapService;

    @Autowired
    private IotBikeClient iotBikeClient;

    @Autowired
    private AgentParamCacheService agentParamCacheService;
    @Resource
    private IEbMemberInfoService memberInfoService;

    @Autowired
    private IEbRideOrderService rideOrderService;

    @ApiOperation("附近的车辆(无需登录)")
    @GetMapping("/near")
    public AjaxResult<List<DeviceBikeVo>> near(MemberLocationForm memberLocationForm) {
        AgentInfo agentInfo = LocalMapUtil.getAgentInfo();
        Assert.notNull(agentInfo.getAreaId(), "缺少运营区ID");
        Assert.notNull(memberLocationForm.getLng(), "缺少lng");
        Assert.notNull(memberLocationForm.getLat(), "缺少lat");
        return AjaxResult.success(deviceBikeService.getNearList(agentInfo.getId(), agentInfo.getAreaId(), memberLocationForm));
    }

    @ApiOperation("获取车辆信息(无需登录)")
    @GetMapping("/detail/{bikeNo}")
    public AjaxResult<DeviceBikeVo> detail(@PathVariable("bikeNo") String bikeNo) {
        Assert.isTrue(StrUtil.isNotBlank(bikeNo), "缺少车辆编号");
        return AjaxResult.success(deviceBikeService.getBike(bikeNo));
    }

    @ApiOperation("步行找车路径规划(无需登录)")
    @PostMapping("/walking/{bikeNo}")
    public AjaxResult<List<RouteVo>> walking(@PathVariable("bikeNo") String bikeNo,
            @RequestBody MemberLocationForm memberLocationForm) {
        Assert.isTrue(StrUtil.isNotBlank(bikeNo), "缺少车辆编号");
        EbDeviceBike deviceBike = deviceBikeService.getByNo(bikeNo);
        if (LnglatUtil.getDistance(deviceBike.getLng().doubleValue(),
                deviceBike.getLat().doubleValue(), memberLocationForm.getLng().doubleValue(),
                memberLocationForm.getLat().doubleValue()) < 20) {
            return AjaxResult.success(new ArrayList<>());
        }
        Route route = amapService.directionWalking(
                memberLocationForm.getLng(), memberLocationForm.getLat(), deviceBike.getLng(),
                deviceBike.getLat());
        List<Path> paths = route.getPaths();
        List<RouteVo> routeList = new ArrayList<>();
        for (int i = 0; i < paths.size(); i++) {
            RouteVo routeVo = new RouteVo();
            Path path = paths.get(i);
            List<Step> stepList = path.getSteps();
            List<JSONObject> steps = new ArrayList<>();
            int idx = 0;
            String poly = "";
            int ll = 0;
            int len = 0;
            for (int j = 0; j < stepList.size(); j++) {
                Step step = stepList.get(j);
                String[] polyStrings = step.getPolyline().split(";");
                len = len + polyStrings.length * 2;
            }
            BigDecimal[] bigDecimals = new BigDecimal[len];
            for (int j = 0; j < stepList.size(); j++) {
                JSONObject stepJson = new JSONObject();
                Step step = stepList.get(j);
                String[] polyStrings = step.getPolyline().split(";");
                for (int k = 0; k < polyStrings.length; k++) {
                    String[] split = polyStrings[k].split(",");
                    poly = poly + split[1]+","+split[0]+";";
                    bigDecimals[ll] = new BigDecimal(split[1]);
                    bigDecimals[ll+1] = new BigDecimal(split[0]);
                    ll = ll + 2;
                }
                int l = (int) poly.chars().filter(c -> c == ',').count();
                int idxEnd = idx + l * 2 - 1;
                stepJson.put("mode", "WALKING");
                stepJson.put("instruction", step.getInstruction());
                stepJson.put("polyline_idx", new Integer[]{idx, idxEnd});
                stepJson.put("road_name", step.getRoad());
                stepJson.put("dir_desc", step.getOrientation());
                stepJson.put("distance", step.getDistance());
                stepJson.put("act_desc", step.getAction());
                stepJson.put("type", step.getWalk_type());
                steps.add(stepJson);
                idx = idxEnd + 1;
            }
            BigDecimal[] polyLine = new BigDecimal[bigDecimals.length];
            polyLine[0] = bigDecimals[0];
            polyLine[1] = bigDecimals[1];
            //前向差分压缩
            for (int t = 2; t < bigDecimals.length ; t++) {
                polyLine[t] = BigDecimal.valueOf(1000000).multiply(bigDecimals[t].subtract(bigDecimals[t-2]));
            }

            routeVo.setPolyline(polyLine);
            routeVo.setSteps(steps);
            routeVo.setDuration( Math.round((float) path.getDuration()/60));
            routeVo.setDistance(path.getDistance());

            routeList.add(routeVo);
        }
        return AjaxResult.success(routeList);
    }
    
    @ApiOperation("取车检查车辆信息(无需登录)")
    @PostMapping("/check/{bikeNo}")
    public AjaxResult check(@PathVariable("bikeNo") String bikeNo,
            @RequestBody MemberLocationForm memberLocationForm) {
        EbDeviceBike deviceBike = deviceBikeService.getByNo(bikeNo);
        deviceBikeService.checkOpenBike(AuthUtil.getAgentUser(), deviceBike, memberLocationForm.getLng(),
                memberLocationForm.getLat());
        AgentInfo agentInfo = LocalMapUtil.getAgentInfo();
        BikeParam param = agentParamCacheService.getParam(agentInfo.getId());
        if (param != null && param.getRideOrderWxPayScore()) {
            // 检查用户是否可以骑行
            AgentUser agentUser = AuthUtil.getAgentUser();
            memberInfoService.checkOpenBike(agentUser, deviceBike.getAgentId(),
                    deviceBike.getAreaId());
        }
        return AjaxResult.success("检查通过");
    }

    @ApiOperation("还车检查车辆信息(废弃)")
    @PostMapping("/close/check/{bikeNo}")
    public AjaxResult closeCheck(@PathVariable("bikeNo") String bikeNo) {
        EbDeviceBike deviceBike = deviceBikeService.getByNo(bikeNo);
        EbRideOrder rideOrder = rideOrderService.getByBike(deviceBike.getId());
        deviceBikeService.checkCloseBike(deviceBike, rideOrder, null, null, AuthUtil.getAgentUser().getId(),
                AuthUtil.getAgentUser().getName());
        BikeAreaParam bikeAreaParam = agentParamCacheService.getParam(deviceBike.getAgentId(), deviceBike.getAreaId());
        return AjaxResult.success("检查通过", new OrderCloseCheckVo(bikeAreaParam == null? CommonConstant.ONE : bikeAreaParam.getUserRideReturnBikeProcess()));
    }

    @ApiOperation("还车检查车辆信息(V2)(废弃)")
    @PostMapping("/close/check/V2/{bikeNo}")
    public AjaxResult closeCheckV2(@PathVariable("bikeNo") String bikeNo,
            @RequestBody CloseBikeCheckForm form) {
        EbDeviceBike deviceBike = deviceBikeService.getByNo(bikeNo);
        EbRideOrder rideOrder = rideOrderService.getByBike(deviceBike.getId());
        deviceBikeService.checkCloseBike(deviceBike, rideOrder, form.getIsDispatch(), form.getPayHelmetMoney(),
                AuthUtil.getAgentUser().getId(), AuthUtil.getAgentUser().getName());
        BikeAreaParam bikeAreaParam = agentParamCacheService.getParam(deviceBike.getAgentId(), deviceBike.getAreaId());
        return AjaxResult.success("检查通过", new OrderCloseCheckVo(bikeAreaParam == null? CommonConstant.ONE : bikeAreaParam.getUserRideReturnBikeProcess()));
    }

    @ApiOperation("寻车响铃")
    @PostMapping("/bell/{bikeNo}")
    public AjaxResult bell(@PathVariable("bikeNo") String bikeNo,
            @RequestBody MemberLocationForm memberLocationForm) {
        SendBikeCommandForm commandForm = new SendBikeCommandForm()
                .setAgentId(LocalMapUtil.getAgentInfo().getId())
                .setBikeNo(bikeNo)
                .setCommand(DeviceCommandEnum.BELL.getType())
                .setUserId(AuthUtil.getAgentUser().getId())
                .setUserName(AuthUtil.getAgentUser().getName())
                .setUserType(UserTypeEnum.MEMBER.getCode());
        return iotBikeClient.sendBikeCommand(commandForm);
    }
}
